#include "posting_quantization.h";

// this should be called once for the collection to compute base of logspace
postingQuantization::postingQuantization(){
  positionIndexStored_ = 0;
  positionIndexOut_ = 0;
  base_ = 1.01;
  double currentCompareValue = pow(base_, 256.0);
  double const VALUE_FOR_COMPARIZON = MAXSC*MAXALPHA/MINSC;

  // choose smallest base that reaches from min to max possible score
  for (; currentCompareValue < VALUE_FOR_COMPARIZON; base_ += 0.01){
	  currentCompareValue = pow(base_, 256.0);
  }

  // Here, the value of base_ has been computed.
  cout << "base_:" << base_ << endl;
}

int postingQuantization::codePostDummy(int termid, double score, unsigned char *data_buffer_write_ptr,unsigned char *data_buffer_read_ptr){
	  int i;
	  float scoreInFloatFormat = static_cast<float>(score);

	  int termidInDebug;
	  float scoreInDebug;

	  i += sizeof(termid);
	  i += sizeof(scoreInFloatFormat);

	  /*
	  // NOT WORKING try1
	  stringstream strs;
	  strs << termid;
	  string temp_str1 = strs.str();
	  strs.str("");
	  strs << scoreInFloatFormat;
	  string temp_str2 = strs.str();
	  cout << "----->" << temp_str1.size() << " " << temp_str2.size() << endl;
	  cout << "----->" << temp_str1 << " " << temp_str2 << endl;
	  */

	  /*
	  // NOT WORKING try2
	  for (unsigned counter = 0; counter < temp_str1.size(); counter ++){
		  data_buffer[positionIndexStored_++] = reinterpret_cast<unsigned char*> ( temp_str1[counter] );
	  }

	  for (unsigned counter = 0; counter < temp_str2.size(); counter ++){
		  data_buffer[positionIndexStored_++] = reinterpret_cast<unsigned char*>( temp_str2[counter] );
	  }
	  */

	  /*
	  // NOT WORKING try3
	  memcpy(&termidInDebug, data_buffer + positionIndexOut_, 4);
	  positionIndexOut_ += 4;

	  memcpy(&scoreInDebug, data_buffer + positionIndexOut_, 4);
	  positionIndexOut_ += 4;
	  */

	  /*
	  // write to the data_buffer
      memcpy(data_buffer_write_ptr, (unsigned char*)&termid, 4); // although sizeof(int) would be better
      data_buffer_write_ptr += 4;
      memcpy(data_buffer_write_ptr, (unsigned char*)&score, 4); // although sizeof(int) would be better
      data_buffer_write_ptr += 4;

      memcpy(&termidInDebug, data_buffer_read_ptr, 4); // although sizeof(int) would be better
      data_buffer_read_ptr += 4;
      memcpy(&scoreInDebug, data_buffer_read_ptr, 4); // although sizeof(int) would be better
      data_buffer_read_ptr += 4;

      cout << "----->" << termid << " " << score << endl;
      cout << "----->" << termidInDebug << " " << scoreInDebug << endl;
      */

      // This method is working but the problem is: I do NOT touch the bit operation AT ALL, laugh at me please
      memcpy(data_buffer_write_ptr, (unsigned char*)&termid, 4); // although sizeof(int) would be better
      data_buffer_write_ptr += 4;
      memcpy(data_buffer_write_ptr, (unsigned char*)&score, 4); // although sizeof(int) would be better
      data_buffer_write_ptr += 4;

      memcpy(&termidInDebug, data_buffer_read_ptr, 4); // although sizeof(int) would be better
      data_buffer_read_ptr += 4;
      memcpy(&scoreInDebug, data_buffer_read_ptr, 4); // although sizeof(int) would be better
      data_buffer_read_ptr += 4;

      cout << i << " " << termid << " " << score << endl;
      cout << i << " " << termidInDebug << " " << scoreInDebug << endl;


      return(i);
}

int postingQuantization::decodePostDummy(int *termid, double *score, unsigned char *data){
	  int i;
	  float scoreInFloatFormat;
	  *termid = (int) data[positionIndexOut_];
	  scoreInFloatFormat = (float) data[positionIndexOut_+4];
	  *score = static_cast<double>(scoreInFloatFormat);
	  positionIndexOut_ += 8;
	  i += sizeof(termid);
	  i += sizeof(scoreInFloatFormat);
	  return(i);
}

int postingQuantization::codePost(int termid, double score, unsigned char *data){
  int i;
  double logval;

  logval = log10(score - MINSC)/log10(base_);  // log basis 10 from <math.h>
  data[0] = (unsigned char)(logval);

  for (i = 1; termid > 127; i++, termid>>=7)
    data[i] = (unsigned char)(termid&127);

  data[i] = (unsigned char)(128+termid);

  return(i+1);
}

int postingQuantization::decodePost(int *termid, double *score, unsigned char *data){
  int i;
  int j;

  *score = MINSC + pow(base_, (double)(data[0]));  //pow() from math.h

  for (i = 1, j = 1; data[i] <= 127; i++, j<<=7)
    *termid += (int)(data[i])*j;

  *termid += ((int)(data[i])-128)*j;

  return(i+1);
}
